package org.steven.crm.core.service.user;

import com.steven.common.utils.DateTimeUtil;
import com.steven.xdb.dbmanager.DBManager;
import com.steven.xdb.pagination.query.AbstractQueryDataList;
import org.apache.commons.lang3.StringUtils;
import org.steven.crm.core.auth.UserAuthHandler;
import org.steven.crm.core.auth.dto.GrantTokenRequest;
import org.steven.crm.core.data.CascadeQueryConfig;
import org.steven.crm.core.data.TableRelation;
import org.steven.crm.core.dto.user.LoginRequest;
import org.steven.crm.core.dto.user.RegisterRequest;
import org.steven.crm.core.exception.ServiceException;
import org.steven.crm.core.query.UserQueryDataList;
import org.steven.crm.core.service.BaseService;
import org.steven.crm.core.service.system.SystemFileService;
import org.steven.crm.core.utils.JSONUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author wuzw
 * @Date 2024/1/10 12:00
 * @Version 1.0
 */
public class UserService extends BaseService {
    private static SystemFileService systemFileService = new SystemFileService();

    private static UserAuthHandler userAuthHandler = new UserAuthHandler();

    @Override
    protected String getTable() {
        return "user";
    }

    @Override
    protected AbstractQueryDataList getQueryDataList() {
        return new UserQueryDataList();
    }

    @Override
    protected String getDataSourceName() {
        return null;
    }

    @Override
    protected List<CascadeQueryConfig> getCascadeQueryConfigs() {
        List<CascadeQueryConfig> cascadeQueryConfigs = new ArrayList<>();
        cascadeQueryConfigs.add(CascadeQueryConfig.builder().build().setSrcColumn("imageFileId")
                .setValue("image").setTableRelation(TableRelation.ONE2ONE)
                .setTargetService(systemFileService).setTargetColumn("id")
                .setTargetTableFields(new String[] {"path", "width", "height"}));

        return cascadeQueryConfigs;
    }

    @Override
    public void beforeCreate(Map<String, String> data) throws Exception {
        if (isExistsNick("", data.get("nick"))) {
            throw new ServiceException("昵称已被使用");
        }
        if (isExistsMobile("", data.get("mobile"))) {
            throw new ServiceException("手机号已被注册");
        }

        if (StringUtils.isNotEmpty(data.get("wxOpenId"))
                && isExistsWxOpenId("", data.get("wxOpenId"))) {
            throw new ServiceException("该微信已经绑定用户");
        }
    }

    @Override
    public void beforeUpdate(String id, Map<String, String> data) throws Exception {
        if (StringUtils.isNotEmpty(data.get("nick")) && isExistsNick(id, data.get("nick"))) {
            throw new ServiceException("昵称已被使用");
        }
        if (StringUtils.isNotEmpty(data.get("mobile"))
                && isExistsMobile(id, data.get("mobile"))) {
            throw new ServiceException("手机号已被注册");
        }
    }

    public Map<String, String> register(RegisterRequest request) throws Exception {
        Map<String, String> user = this.create(JSONUtil.toMap(request));
        return user;
    }

    public Map<String, String> login(LoginRequest request) throws Exception {
        GrantTokenRequest grantTokenRequest = GrantTokenRequest.builder().build()
                .setClientId(request.getClientId())
                .setUsername(request.getMobile()).setCode(request.getCode());

        Map<String, String> token = userAuthHandler.grant(grantTokenRequest);

        if (StringUtils.isNotEmpty(token.get("userId"))) {
            Map<String, String> updateV = new HashMap<>();
            updateV.put("loginTime", DateTimeUtil.getCurrentDateTime());
            this.update(token.get("userId"), updateV);
        }

        return token;
    }

    public boolean isExistsNick(String id, String nick) throws Exception {
        Map<String, String> k = new HashMap<>();
        k.put("nick", nick);
        k.put("deleted", "0");
        Map<String, String> data = DBManager.queryOne(getSession(), getTable(), k);

        return !data.isEmpty() && !data.get("id").equals(id);
    }

    public boolean isExistsMobile(String id, String mobile) throws Exception {
        Map<String, String> data = readByMobile(mobile);

        return !data.isEmpty() && !data.get("id").equals(id);
    }

    public Map<String, String> readByMobile(String mobile) throws Exception {
        Map<String, String> k = new HashMap<>();
        k.put("mobile", mobile);
        k.put("deleted", "0");
        return DBManager.queryOne(getSession(), getTable(), k);
    }

    public boolean isExistsWxOpenId(String id, String wxOpenId) throws Exception {
        Map<String, String> data = readByWxOpenId(wxOpenId);

        return !data.isEmpty() && !data.get("id").equals(id);
    }

    public Map<String, String> readByWxOpenId(String wxOpenId) throws Exception {
        Map<String, String> k = new HashMap<>();
        k.put("wxOpenId", wxOpenId);
        k.put("deleted", "0");
        return DBManager.queryOne(getSession(), getTable(), k);
    }
}
